﻿// ## 2024/1/3 # 铃 # 根据新地图的特点,重构逻辑,调整参数##
// ## 2023/05/13 # 江东新风 # 适配血色，暂时将参数调回0328设置 ##
// ## 2023/04/12 # 铃 # 为了适配淡然做的山地和山路地形,把高度禁入和悬崖路禁入取消 ##
// ## 2023/04/12 # 铃 # 完全翻译 ##
// ## 2020/10/30 #江东新风#同步马术书大神的更新##
// ## 2020/08/03 #messi#改进表述##



namespace 地形移动限制
{
    const bool 城市周围地形_更改设置 = true;
    const bool 小城周围地形_更改设置 = true;
    const bool 府周围地形_更改设置 = true;
    const bool 高差过高地形_更改设置 = true;
    const bool 内政周围地形_更改设置 = true;
    const bool 水系相关_更改设置 = true;
    const bool 孤岛地形_更改设置 = true;

    const int  高地地形_标准高度_西蜀南蛮 = 180;      // 注意事项 : 不可低于 180 设置
    const int  高地地形_标准高度_其他区域 = 130;

        //---------------------------------------------------------------------------------------

    class Main
    {

        Main()
        {
            pk::bind(102, pk::trigger102_t(onGameInit));
            pk::bind(106, pk::trigger106_t(onLoad)); // 在读档前
            pk::bind2(102, pk::trigger102_t(onLoad2), -999);
            //pk::bind2(102, pk::trigger102_t(剧本初始化_结构体_信息读取),999);
            //pk::bind(105, pk::trigger105_t(remove_invalid_object1));
            //pk::bind(106, pk::trigger106_t(remove_invalid_object1));
            pk::bind(112, pk::trigger112_t(remove_invalid_object3));
            pk::bind(112, pk::trigger112_t(onTurnEnd));
            //pk::bind(111, pk::trigger111_t(remove_invalid_object3));

        }

        void onLoad(int file_id, pk::s11reader@ r)
        {
            for (int pos_x = 0; pos_x < 200; pos_x++)
            {
                for (int pos_y = 0; pos_y < 200; pos_y++)
                {
                    pk::point pos;
                    pos.x = pos_x;
                    pos.y = pos_y;

                    pk::hex@ hex = pk::get_hex(pos);

                   // if (pk::get_world_object(hex.object) !is null and pk::get_world_object(hex.object).model>=0x2e and pk::get_world_object(hex.object).model<=0x3d)
                    if (pk::get_model_id(pos) >= 46 and pk::get_model_id(pos) <= 61)
                    {
                        //pk::trace(pk::format("{},{},对象{}", pos.x, pos.y, pk::get_model_id(pos)));
                        hex.terrain = 地形_森;
                    }
                    if (pk::get_model_id(pos) >= 10 and pk::get_model_id(pos) <= 16)
                    {
                        //pk::trace(pk::format("{},{},对象{}", pos.x, pos.y, pk::get_model_id(pos)));
                        hex.terrain = 地形_荒地;
                    }

                    if (pk::get_model_id(pos) == 20 or pk::get_model_id(pos) == 45)
                    {
                        //pk::trace(pk::format("{},{},对象{}", pos.x, pos.y, pk::get_model_id(pos)));
                        hex.terrain = 地形_荒地;
                    }

                    if (pos.x == 91 and pos.y == 95) hex.terrain = 地形_湿地;
                    if (pos.x == 30 and pos.y ==86) hex.terrain = 地形_土;


                        // if(pos.x ==92 and pos.y==96) hex.terrain = 地形_湿地;
                        // if(pos.x ==93 and pos.y==96) hex.terrain = 地形_湿地;

                }

            }

                                //限制上郡隘口附近的建筑
            // pk::point pos2;
            // pos2.x = 49;
            // pos2.y = 30;
            // pk::array<pk::point> range = pk::range(pos2, 0, 3);
            // for (int j = 0; j < int(range.length); j++)
            // {
            //     pk::hex@ hex = pk::get_hex(range[j]);
            //     if (hex.terrain == 地形_官道 or hex.terrain == 地形_砂地)
            //     {
            //         hex.terrain = 地形_荒地;
            //     }
            // }

            //  //限制飞狐陉附近的建筑
            // pos2.x = 106;
            // pos2.y = 12;
            // range = pk::range(pos2, 0, 3);
            // for (int j = 0; j < int(range.length); j++)
            // {
            //     pk::hex@ hex = pk::get_hex(range[j]);
            //     if (hex.terrain == 地形_草地 or hex.terrain == 地形_官道)
            //     {
            //         hex.terrain = 地形_荒地;
            //     }
            // }

            //  //限制长坂坡附近的建筑
            // pos2.x = 82;
            // pos2.y = 125;
            // range = pk::range(pos2, 0, 3);
            // for (int j = 0; j < int(range.length); j++)
            // {
            //     pk::hex@ hex = pk::get_hex(range[j]);
            //     if (hex.terrain == 地形_草地 or hex.terrain == 地形_官道)
            //     {
            //         hex.terrain = 地形_渡;
            //     }
            // }

        }

        void onLoad2()
        {
            disable_terrain_development();
        }

        void onGameInit()
        {
            if (城市周围地形_更改设置)
            {
                for (int num = 建筑_城市开始; num < 城市_末; num++)
                {
                    disable_terrain_around_building(num, 3);
                }
            }

            if (小城周围地形_更改设置)
            {
                for (int num = 城市_末; num < 据点_末; num++)
                {
                    int range = 7;
                    if (ch::is_gate(num))
                        range = 7;
                    else range = 2;
                    disable_terrain_around_building(num, range);
                }
            }

            if (府周围地形_更改设置)
            {
                disable_terrain_around_spec();

            }

            if (高差过高地形_更改设置)
            {
                disable_terrain_high_pos();
            }

            if (高差过高地形_更改设置)
            {
                disable_terrain_near_high_pos();
            }


            if (水系相关_更改设置)
            {
                disable_terrain_near_lots_hill();
                disable_terrain_near_river();
                disable_terrain_near_river2();
            }


            if (内政周围地形_更改设置)
            {
               // disable_terrain_development();
            }

            if (孤岛地形_更改设置)
            {
                disable_terrain_around_cliff();
                disable_terrain_around_wall();
                disable_terrain_near_null_pos();
                disable_terrain_near_null_pos();
            }

            remove_invalid_object();

        }


        void onTurnEnd(pk::force@ force)
        {
            if (pk::is_campaign()) return;
            remove_invalid_object();
        }

        //---------------------------------------------------------------------------


        void disable_terrain_around_spec()
        {
            for (int i = 0; i < ch::get_spec_end(); i += 1)
            {
                pk::point pos0 = ch::get_spec_pos(i);
                pk::array<pk::point> range = pk::range(pos0, 1, 1);
                for (int j = 0; j < int(range.length); j++)
                {
                    pk::hex@ hex = pk::get_hex(range[j]);
                    if (hex.terrain == 地形_崖 or hex.terrain == 地形_岸)
                    {
                        hex.terrain = 地形_未定;
                    }
                }
            }
        }

        void disable_terrain_around_building(int building_id, int around_range)
        {
            pk::building@ building = pk::get_building(building_id);
            //pk::trace(pk::format("building_id{},around_range{}", building_id,around_range));
            pk::array<pk::point> range = pk::range(building.pos, 1, around_range);
            for (int j = 0; j < int(range.length); j++)
            {
                pk::hex@ hex = pk::get_hex(range[j]);
                if (hex.terrain == 地形_崖 or hex.terrain == 地形_岸)
                {
                    hex.terrain = 地形_未定;
                }
            }

        }

        void disable_terrain_high_pos()
        {
            for (int pos_x = 0; pos_x < 200; pos_x++)
            {
                for (int pos_y = 0; pos_y < 200; pos_y++)
                {
                    pk::point pos;
                    pos.x = pos_x;
                    pos.y = pos_y;

                    pk::hex@ hex = pk::get_hex(pos);

                    // 지방별 기준높이
                    int region_id = pk::get_region_id(pk::get_city(pk::get_city_id(pos)));
                    int ref_height = 0;
                    if (region_id >= 地方_巴蜀)
                        ref_height = pk::max(180, 高地地形_标准高度_西蜀南蛮);
                    else
                        ref_height = pk::max(100, 高地地形_标准高度_其他区域);

                    int pos_height = pk::get_height_map(pk::hex_pos_to_height_map_pos(pos) + 2).height;
                    if (hex.terrain == 地形_崖 and pos_height >= ref_height)
                    {
                        hex.terrain = 地形_未定;

                        pk::array<pk::point> range = pk::range(pos, 1, 2);
                        for (int j = 0; j < int(range.length); j++)
                        {
                            pk::hex@ hex0 = pk::get_hex(range[j]);
                            if (hex0.terrain == 地形_崖 or hex0.terrain == 地形_岸)
                            {
                                hex0.terrain = 地形_未定;
                            }
                        }

                    }
                }
            }
        }

        //长城附近移动限制
        void disable_terrain_around_wall()
        {
            {
                for (int pos_x = 0; pos_x < 200; pos_x++)
                {
                    for (int pos_y = 0; pos_y < 200; pos_y++)
                    {
                        pk::point pos;
                        pos.x = pos_x;
                        pos.y = pos_y;

                        pk::hex@ hex = pk::get_hex(pos);
                        if (pk::get_model_id(pos) == 14)
                        {
                            pk::array<pk::point> range = pk::range(pos, 1, 1);
                            for (int j = 0; j < int(range.length); j++)
                            {
                                pk::hex@ hex0 = pk::get_hex(range[j]);

                                hex0.terrain = 地形_未定;

                            }
                        }
                    }
                }
            }
        }


        void disable_terrain_around_cliff()
        {
            {
                for (int pos_x = 0; pos_x < 200; pos_x++)
                {
                    for (int pos_y = 0; pos_y < 200; pos_y++)
                    {
                        pk::point pos;
                        pos.x = pos_x;
                        pos.y = pos_y;

                        pk::hex@ hex = pk::get_hex(pos);
                        if (hex.terrain == 地形_栈道 or pk::get_model_id(pos) == 14)
                        {
                            pk::array<pk::point> range = pk::range(pos, 1, 2);
                            for (int j = 0; j < int(range.length); j++)
                            {
                                pk::hex@ hex0 = pk::get_hex(range[j]);
                                if (hex0.terrain == 地形_崖 or hex0.terrain == 地形_岸)
                                {
                                    hex0.terrain = 地形_未定;
                                }
                            }
                        }
                    }
                }
            }
        }


        //过于陡峭的山上不去,
        void disable_terrain_near_high_pos()
        {
            for (int pos_x = 0; pos_x < 200; pos_x++)
            {
                for (int pos_y = 0; pos_y < 200; pos_y++)
                {
                    pk::point pos;
                    pos.x = pos_x;
                    pos.y = pos_y;

                    pk::hex@ hex = pk::get_hex(pos);
                    if (hex.terrain == 地形_崖)
                    {
                        int pos_height = pk::get_height_map(pk::hex_pos_to_height_map_pos(pos) + 2).height;
                        int max_height = 0;
                        for (int dir = 0; dir < 方向_末; dir++)
                        {
                            pk::point neighbor_pos = pk::get_neighbor_pos(pos, dir);

                            if (pk::is_valid_pos(neighbor_pos))
                            {
                                pk::hex@ neighbor_hex = pk::get_hex(neighbor_pos);
                                int neighbor_height = pk::get_height_map(pk::hex_pos_to_height_map_pos(neighbor_pos) + 2).height;
                                if ((pos_height >= neighbor_height + 60))

                                    hex.terrain = 地形_未定;

                            }
                        }

                    }
                }
            }
        }

        //山中间设为未定
        void disable_terrain_near_lots_hill()
        {
            for (int pos_x = 0; pos_x < 200; pos_x++)
            {
                for (int pos_y = 0; pos_y < 200; pos_y++)
                {
                    pk::point pos;
                    pos.x = pos_x;
                    pos.y = pos_y;
                    int count_hill = 0;
                    bool has_very_high = false;
                    int count = 0;

                    pk::hex@ hex = pk::get_hex(pos);
                    if (hex.terrain == 地形_崖)
                    {
                        pk::array<pk::point> range = pk::range(pos, 1, 5);

                        for (int j = 0; j < int(range.length); j++)
                        {
                            if (pk::is_valid_pos(range[j]))
                            {
                                pk::hex@ hex0 = pk::get_hex(range[j]);

                                if (hex0.terrain == 地形_崖 or hex0.terrain == 地形_岸 or hex0.terrain == 地形_川 or hex0.terrain == 地形_未定 or hex0.terrain == 地形_河)
                                {
                                    if (pk::get_height_map(pk::hex_pos_to_height_map_pos(range[j]) + 2).height >= 150)
                                    {
                                        has_very_high = true;
                                        break;
                                    }
                                }

                            }
                        }

                        int range_int = 0;
                        if (has_very_high) range_int = 2;
                        else range_int = 5;
                        range = pk::range(pos, 1, range_int);

                        for (int j = 0; j < int(range.length); j++)
                        {
                            if (pk::is_valid_pos(range[j]))
                            {
                                pk::hex@ hex0 = pk::get_hex(range[j]);
                                count++;

                                if (hex0.terrain == 地形_崖 or hex0.terrain == 地形_岸 or hex0.terrain == 地形_川 or hex0.terrain == 地形_未定 or hex0.terrain == 地形_河)
                                {
                                    count_hill++;
                                }

                            }
                        }
                        if (count_hill >= count - 1) hex.terrain = 地形_未定;
                        //pk::trace(pk::format("{},{},计数{},{},是否有高点{}", pos.x, pos.y, count_hill, count,has_very_high));
                    }
                }
            }
        }

        //河附近的崖也不能攀登
        void disable_terrain_near_river2()
        {
            for (int pos_x = 0; pos_x < 200; pos_x++)
            {
                for (int pos_y = 0; pos_y < 200; pos_y++)
                {
                    pk::point pos;
                    pos.x = pos_x;
                    pos.y = pos_y;
                    int count_river = 0;
                    int count = 0;

                    pk::hex@ hex = pk::get_hex(pos);
                    if (hex.terrain == 地形_崖)
                    {
                        pk::array<pk::point> range = pk::range(pos, 1, 2);
                        for (int j = 0; j < int(range.length); j++)
                        {
                            if (pk::is_valid_pos(range[j]))
                            {
                                pk::hex@ hex0 = pk::get_hex(range[j]);
                                count++;

                                if (hex0.terrain == 地形_河 or hex0.terrain == 地形_川 or hex0.terrain == 地形_海)
                                {
                                    count_river++;
                                }

                            }
                        }
                        if (count_river >= 3 and pk::get_height_map(pk::hex_pos_to_height_map_pos(pos) + 2).height > 50) hex.terrain = 地形_未定;
                       // pk::trace(pk::format("{},{},计数{},{}", pos.x, pos.y, count_hill, count));
                    }
                }
            }
        }

        //河里不能直接攀登崖
        void disable_terrain_near_river()
        {
            for (int pos_x = 0; pos_x < 200; pos_x++)
            {
                for (int pos_y = 0; pos_y < 200; pos_y++)
                {
                    pk::point pos;
                    pos.x = pos_x;
                    pos.y = pos_y;
                    int count_hill = 0;
                    int count = 0;

                    pk::hex@ hex = pk::get_hex(pos);
                    int pos_height = pk::get_height_map(pk::hex_pos_to_height_map_pos(pos) + 2).height;
                    if (hex.terrain == 地形_崖)
                    {
                        pk::array<pk::point> range = pk::range(pos, 1, 1);
                        for (int j = 0; j < int(range.length); j++)
                        {
                            if (pk::is_valid_pos(range[j]))
                            {
                                pk::hex@ hex0 = pk::get_hex(range[j]);
                                if (hex0.terrain == 地形_河)
                                {
                                    int neighbor_height = pk::get_height_map(pk::hex_pos_to_height_map_pos(range[j]) + 2).height;
                                    if (pos_height - neighbor_height > 10) hex.terrain = 地形_未定;
                                }

                            }
                        }
                       // pk::trace(pk::format("{},{},计数{},{}", pos.x, pos.y, count_hill, count));
                    }
                }
            }
        }


        //孤岛设为未定
        void disable_terrain_near_null_pos()
        {
            for (int pos_x = 0; pos_x < 200; pos_x++)
            {
                for (int pos_y = 0; pos_y < 200; pos_y++)
                {
                    pk::point pos;
                    pos.x = pos_x;
                    pos.y = pos_y;
                    int count_valid = 0;

                    pk::hex@ hex = pk::get_hex(pos);
                    if (hex.terrain == 地形_崖)
                    {
                        for (int dir = 0; dir < 方向_末; dir++)
                        {
                            pk::point neighbor_pos = pk::get_neighbor_pos(pos, dir);
                            if (pk::is_valid_pos(neighbor_pos))
                            {
                                pk::hex@ hex0 = pk::get_hex(neighbor_pos);

                                if (hex0.terrain != 地形_岸 and hex0.terrain != 地形_川 and hex0.terrain != 地形_未定)
                                {
                                    count_valid++;
                                }


                            }
                        }
                        if (count_valid <= 1)
                            hex.terrain = 地形_未定;
                       // pk::trace(pk::format("{},{},计数{}", pos.x, pos.y, count_valid));
                        //pk::trace(pk::format("{},{}邻居格子:{},{},计数{},{}", pos.x, pos.y, neighbor_pos.x, neighbor_pos.y, count_valid));

                    }
                }

            }
        }




       //内政周围2格用地的崖设为未定
        void disable_terrain_development()
        {
            for (int pos_x = 0; pos_x < 200; pos_x++)
            {
                for (int pos_y = 0; pos_y < 200; pos_y++)
                {
                    pk::point pos;
                    pos.x = pos_x;
                    pos.y = pos_y;

                    pk::hex@ hex = pk::get_hex(pos);
                    //pk::trace(pk::format("{},{},是否可建设{},id{}", pos.x, pos.y, hex.development, pk::get_model_id(pos)));
                    if (hex.development or pk::get_model_id(pos) == 45)
                    {
                        pk::array<pk::point> range = pk::range(pos, 1, 2);
                        for (int j = 0; j < int(range.length); j++)
                        {
                            if (pk::is_valid_pos(range[j]))
                            {
                                pk::hex@ hex0 = pk::get_hex(range[j]);

                                if (hex0.terrain == 地形_崖)
                                {
                                    hex0.terrain = 地形_未定;
                                }

                            }
                        }
                    }
                }
            }

        }



        void remove_invalid_object()
        {
            for (int pos_x = 0; pos_x < 200; pos_x++)
            {
                for (int pos_y = 0; pos_y < 200; pos_y++)
                {
                    pk::point pos;
                    pos.x = pos_x;
                    pos.y = pos_y;

                    pk::hex@ hex = pk::get_hex(pos);
                    if (hex.terrain == 地形_未定 and hex.has_unit)
                        pk::kill(pk::get_unit(pos));

                    if (hex.terrain == 地形_未定 and hex.has_building)
                        pk::kill(pk::get_building(pos));
                    //增加当建筑物和单位重疊的处理by江东新风

                    //if (hex.has_unit and hex.has_building)
                        // pk::kill(pk::get_unit(pos));
                }
            }

        }


        void remove_invalid_object3(pk::force@ force)
        {
            array<pk::unit@> arr = pk::list_to_array(pk::get_unit_list());
            for (int i = 0; i < int(arr.length); i++)
            {
                pk::unit@ dst = arr[i];
                pk::point pos = dst.pos;
                pk::hex@ hex = pk::get_hex(pos);
                if (hex.has_building)
                {
                    pk::history_log(dst.get_pos(), force.color, pk::encode(pk::format("\x1b[1x{}\x1b[0x内部士兵与主将出现了分歧,士兵们解甲归田了.", pk::decode(pk::get_name(dst)))));
                    pk::kill(dst);
                }

            }

        }



    }

    Main main;
}

